package org.xiaojinlong.explore;


/**
 * Jin Long
 * 2015/3/30
 */
public class Exp {
    static List<Integer> doubleAll(List<Integer> xs) {
        return List.map(i -> i * 2, xs);
    }

    static int countNs(List<Integer> xs, Integer n) {
        return List.length(List.filter(a -> a.equals(n), xs));
    }

    public static void main(String[] args) {
//        LinkedList<Integer> l = new LinkedList<>();
//        l.add(2); l.add(3); l.add(4);
//        System.out1.println(l.poll());
//        System.out1.println(l);
        List<Integer> test = new List<>(1, new List<>(2, null));
        System.out.println(doubleAll(test));

    }
}

interface Func<B, A> { B m(A a); }
interface Pred<A> { boolean m(A a); }

class List<T> {
    T head;
    List<T> tail;
    List(T x, List<T> xs) {
        head = x;
        tail = xs;
    }

    static <A, B> List<B> map(Func<B, A> f, List<A> xs) {
        if (xs == null)
            return null;
        return new List<>(f.m(xs.head), map(f, xs.tail));
    }

    static <A> List<A> filter(Pred<A> f, List<A> xs) {
        if (xs == null)
            return null;
        if (f.m(xs.head))
            return new List<A>(xs.head, filter(f, xs.tail));
        return filter(f, xs.tail);
    }

    static <A> int length(List<A> xs) {
        int len = 0;
        do {
            if (xs.head != null)
                len++;
            xs = xs.tail;
        } while (xs != null);
        return len;
    }

    @Override
    public String toString() {
        if (tail == null)
            return head.toString();
        else
            return head + " " + tail.toString();
    }

}


// A more OO approach would be instance methods
// 不能在null上面调用方法 导致客户端代码必须处理null的情况
// An even more OO alternative uses a subclass of List for empty-lists
// rather than null -- Then instance methods work fine!
